package controller

import (
	captcha "Short_chain_cats/captcha/puzzle_captcha"
	"Short_chain_cats/database"
	"Short_chain_cats/util"
	"crypto/md5"
	"encoding/json"
	"fmt"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/go-redis/redis/v8"
	uuid "github.com/satori/go.uuid"
)

// Data 用于返回验证码的图片数据和 token
type Data struct {
	OrgImg string `json:"originalImageBase64"` //原始图片
	BlkImg string `json:"jigsawImageBase64"`   //缺口图片
	Token  string `json:"token"`
	//X      int    `json:"x"` //y坐标
	Y int `json:"y"` //y坐标
}

type Item struct {
	Point *captcha.Point `json:"point"` //滑块位置坐标
}

// CheckParams 接收校验请求
type CheckParams struct {
	Point *captcha.Point `json:"point"` //校验滑块位置坐标
	Token string         `json:"token"`
}

// VerificationParams 二次验证请求
type VerificationParams struct {
	Verification string `json:"verification"` //二次校验token
}

func GetCaptcha(ctx *gin.Context) {
	ret, err := captcha.Run() // 生成验证码图片和滑动位置
	if err != nil {
		util.RespFailed(ctx, util.CaptchaFailed, util.Translate(err))
		return
	}
	//将生成的图片和 token 返回给前端，并将 token 和滑动位置缓存
	data := &Data{
		BlkImg: ret.BlockImg,
		OrgImg: ret.BackgroudImg,
		Token:  uuid.NewV4().String(),
		//X:      ret.Point.X,
		Y: ret.Point.Y,
	}
	item := &Item{
		Point: ret.Point,
	}
	itemJson, _ := json.Marshal(item)
	err = database.RedisClient.Set(ctx, "puzzle_captcha:first:point", itemJson, 3*time.Minute).Err()   // 存储到 Redis 中，设置3分钟过期时间
	err = database.RedisClient.Set(ctx, "puzzle_captcha:first:token", data.Token, 3*time.Minute).Err() // 存储到 Redis 中，设置3分钟过期时间
	if err != nil {
		util.RespFailed(ctx, util.Failed, util.Translate(err))
		return
	}
	util.RespSuccess(ctx, "data里面是原始图片，生成的图片和token", data)
}

func CheckCaptcha(ctx *gin.Context) {
	var param CheckParams
	if err := ctx.ShouldBindJSON(&param); err != nil {
		util.RespFailed(ctx, util.ParamError, util.Translate(err))
		return
	}
	//检查 token 是否存在以及是否过期
	itemJson, err := database.RedisClient.Get(ctx, "puzzle_captcha:first:point").Result()
	tokenJson, err := database.RedisClient.Get(ctx, "puzzle_captcha:first:token").Result()
	if err == redis.Nil || err != nil {
		util.RespFailed(ctx, util.RedisFailed, util.Translate(err))
		return
	}
	if param.Token != tokenJson {
		util.RespFailed(ctx, util.VerificationFailed, "")
		return
	}
	var item Item
	json.Unmarshal([]byte(itemJson), &item)
	// 校验用户滑动位置是否正确
	if err = captcha.Check(param.Point, item.Point); err != nil {
		util.RespFailed(ctx, util.Failed, util.Translate(err))
		return
	}
	//else {
	//	// 如果校验通过，生成一个二次验证的 key，并缓存该 key
	//	verificationKey := fmt.Sprintf("%s",
	//		md5Str(fmt.Sprintf("%s---%d---%d", param.Token, param.Point.X, param.Point.Y)))
	//	//verificationJson, _ := json.Marshal(&VerificationParams{
	//	//	Verification: verificationKey,
	//	//})
	//	err = database.RedisClient.Set(ctx, "puzzle_captcha:second:verification", verificationKey, 3*time.Minute).Err() // 设置3分钟过期时间
	//	if err != nil {
	//		util.RespFailed(ctx, util.RedisFailed, translate(err))
	//		return
	//	}
	//util.RespSuccess(ctx, "data里面是二次校验token", VerificationParams{Verification: verificationKey})
	//}
	util.RespSuccess(ctx, "滑动验证码验证成功", nil)
}

//func VerifyCaptcha(ctx *gin.Context) {
//	var param VerificationParams
//	// 使用 ctx.ShouldBindJSON 来绑定请求数据并进行验证
//	if err := ctx.ShouldBindJSON(&param); err != nil {
//		util.RespFailed(ctx, util.ParamError, translate(err))
//		return
//	}
//	//检查二次验证的 key 是否存在以及是否过期
//	verification, err := database.RedisClient.Get(ctx, "puzzle_captcha:second:verification").Result()
//	if err == redis.Nil || err != nil {
//		util.RespFailed(ctx, util.RedisFailed, translate(err))
//		return
//	}
//	if verification != param.Verification {
//		util.RespFailed(ctx, util.VerificationFailed, translate(err))
//		return
//	} else {
//		util.RespSuccess(ctx, "验证成功", nil)
//	}
//}

func md5Str(str string) string {
	data := []byte(str)
	has := md5.Sum(data)
	md5str := fmt.Sprintf("%x", has)
	return md5str
}
